package com.foundationmade.newbiz.business.foundation.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.foundationmade.newbiz.business.foundation.domain.Foundation;
import com.foundationmade.newbiz.business.foundation.service.FoundationService;

import devcken.datatables.serverside.FromServer;
import devcken.datatables.serverside.SortQuery;
import devcken.datatables.serverside.ToServer;
import devcken.hibernate.query.OrderBy;
import devcken.lang.NumberParser;
import devcken.utility.Pair;

/**
 * 매장 관련 요청을 처리하기 위한 인터페이스를 제공한다. 
 * @author Devcken
 */
@Controller
@RequestMapping("/foundation")
public class FoundationController
{
	private final static Logger logger = LoggerFactory.getLogger(FoundationController.class);
	
	/**
	 * 매장 관련 DAO를 주입받는다.
	 */
	@Resource(name="foundationService")
	private FoundationService _foundationService;
	
	/**
	 * 매장 메인 페이지로 이동한다.
	 * @return 매장 메인 페이지에 대한 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RolesAllowed("ROLE_ADMIN")
	@RequestMapping(value = StringUtils.EMPTY, method = { RequestMethod.GET, RequestMethod.POST })
	public ModelAndView foundationMain()
	{
		return new ModelAndView("foundation.list");
	}
	
	/**
	 * 매장 보고서 페이지로 이동한다.
	 * @param foundationId 보고서를 보려는 매장의 아이디가 전달된다.
	 * @return 매장 보고서 페이지에 대한 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RolesAllowed("ROLE_ADMIN")
	@RequestMapping(value = "/report", method = { RequestMethod.GET, RequestMethod.POST })
	public ModelAndView foundationReport(@RequestParam(value = "foundationId", required = true) Long foundationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		Foundation foundation = this._foundationService.getFoundation(foundationId);
		
		map.put("foundation", foundation);
		
		return new ModelAndView("foundation.report", map);
	}
	
	/**
	 * 매장 조회 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param searchCondition 매장 검색 조건이 전달된다.
	 * @param searchLeaseDepositLow 매장 검색 조건 중 임대 보증금 하한값이 전달된다.
	 * @param searchLeaseDepositHigh 매장 검색 조건 중 임대 보증금 상한값이 전달된다.
	 * @param searchFacilitiesInvestmentLow 매장 검색 조건 중 시설 투자금 하한값이 전달된다.
	 * @param searchFacilitiesInvestmentHigh 매장 검색 조건 중 시설 투자금 상한값이 전달된다. 
	 * @param searchUnionFeeLow 매장 검색 조건 중 가맹비 하한값이 전달된다.
	 * @param searchUnionFeeHigh 매장 검색 조건 중 가맹비 상한값이 전달된다.
	 * @param searchTotalFeeLow 매장 검색 조건 중 합계 하한값이 전달된다.
	 * @param searchTotalFeeHigh 매장 검색 조건 중 합계 상한값이 전달된다.
	 * @param searchMonthlyRentalFeeLow 매장 검색 조건 중 월세/관리비 하한값이 전달된다.
	 * @param searchMonthlyRentalFeeHigh 매장 검색 조건 중 월세/관리비 상한값이 전달된다.
	 * @param searchCommisionLow 매장 검색 조건 중 수수료/관리비 하한값이 전달된다.
	 * @param searchCommisionHigh 매장 검색 조건 중 수수료/관리비 상한값이 전달된다.
	 * @param searchServiceChargeLow 매장 검색 조건 중 용역비 하한값이 전달된다.
	 * @param searchServiceChargeHigh 매장 검색 조건 중 용역비 상한값이 전달된다.
	 * @param searchSalesPerDayLow 매장 검색 조건 중 일매출 하한값이 전달된다.
	 * @param searchSalesPerDayHigh 매장 검색 조건 중 일매출 상한값이 전달된다.
	 * @param searchSalesPerMonthLow 매장 검색 조건 중 월매출 하한값이 전달된다.
	 * @param searchSalesPerMonthHigh 매장 검색 조건 중 월매출 상한값이 전달된다.
	 * @return 매장 조회 결과를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RolesAllowed("ROLE_ADMIN")
	@RequestMapping(value = "/list", method = { RequestMethod.POST })
	public ModelAndView listFoundations(HttpServletRequest request,
			ToServer toServer,
			Foundation searchCondition,
			@RequestParam(value = "searchLeaseDeposit", required = false)String searchLeaseDeposit,
			@RequestParam(value = "searchFacilitiesInvestment", required = false)String searchFacilitiesInvestment,
			@RequestParam(value = "searchPremium", required = false)String searchPremium,
			@RequestParam(value = "searchUnionFee", required = false)String searchUnionFee,
			@RequestParam(value = "searchSupportFund", required = false)String searchSupportFund,
			@RequestParam(value = "searchTotalFee", required = false)String searchTotalFee,
			@RequestParam(value = "searchMonthlyRentalFee", required = false)String searchMonthlyRentalFee,
			@RequestParam(value = "searchCommision", required = false)String searchCommision,
			@RequestParam(value = "searchServiceCharge", required = false)String searchServiceCharge,
			@RequestParam(value = "searchSalesPerDay", required = false)String searchSalesPerDay,
			@RequestParam(value = "searchSalesPerMonth", required = false)String searchSalesPerMonth)
	{
		FromServer map = new FromServer();
		
		try
		{
			Integer searchLeaseDepositLow = null;
			Integer searchLeaseDepositHigh = null;
			Integer searchFacilitiesInvestmentLow = null;
			Integer searchFacilitiesInvestmentHigh = null;
			Integer searchPremiumLow = null;
			Integer searchPremiumHigh = null;
			Integer searchUnionFeeLow = null;
			Integer searchUnionFeeHigh = null;
			Integer searchSupportFundLow = null;
			Integer searchSupportFundHigh = null;
			Integer searchTotalFeeLow = null;
			Integer searchTotalFeeHigh = null;
			Integer searchMonthlyRentalFeeLow = null;
			Integer searchMonthlyRentalFeeHigh = null;
			Integer searchCommisionLow = null;
			Integer searchCommisionHigh = null;
			Float searchServiceChargeLow = null;
			Float searchServiceChargeHigh = null;
			Integer searchSalesPerDayLow = null;
			Integer searchSalesPerDayHigh = null;
			Integer searchSalesPerMonthLow = null;
			Integer searchSalesPerMonthHigh = null;
			
			if (StringUtils.isNotEmpty(searchLeaseDeposit))
			{
				String[] searchLeaseDeposits = searchLeaseDeposit.split("~");
				
				if (searchLeaseDeposits.length == 2)
				{
					searchLeaseDepositLow = NumberParser.parseToInt(searchLeaseDeposits[0], 0);
					searchLeaseDepositHigh = NumberParser.parseToInt(searchLeaseDeposits[1], 0) - 1;
				}
				else
				{
					searchLeaseDepositLow = NumberParser.parseToInt(searchLeaseDeposits[0], 0);
					searchLeaseDepositHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchFacilitiesInvestment))
			{
				String[] searchFacilitiesInvestments = searchFacilitiesInvestment.split("~");
				
				if (searchFacilitiesInvestments.length == 2)
				{
					searchFacilitiesInvestmentLow = NumberParser.parseToInt(searchFacilitiesInvestments[0], 0);
					searchFacilitiesInvestmentHigh = NumberParser.parseToInt(searchFacilitiesInvestments[1], 0) - 1;
				}
				else
				{
					searchFacilitiesInvestmentLow = NumberParser.parseToInt(searchFacilitiesInvestments[0], 0);
					searchFacilitiesInvestmentHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchPremium))
			{
				String[] searchPremiums = searchPremium.split("~");
				
				if (searchPremiums.length == 2)
				{
					searchPremiumLow = NumberParser.parseToInt(searchPremiums[0], 0);
					searchPremiumHigh = NumberParser.parseToInt(searchPremiums[1], 0) - 1;
				}
				else
				{
					searchPremiumLow = NumberParser.parseToInt(searchPremiums[0], 0);
					searchPremiumHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchUnionFee))
			{
				String[] searchUnionFees = searchUnionFee.split("~");
				
				if (searchUnionFees.length == 2)
				{
					searchUnionFeeLow = NumberParser.parseToInt(searchUnionFees[0], 0);
					searchUnionFeeHigh = NumberParser.parseToInt(searchUnionFees[1], 0) - 1;
				}
				else
				{
					searchUnionFeeLow = NumberParser.parseToInt(searchUnionFees[0], 0);
					searchUnionFeeHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchSupportFund))
			{
				String[] searchSupportFunds = searchSupportFund.split("~");
				
				if (searchSupportFunds.length == 2)
				{
					searchSupportFundLow = NumberParser.parseToInt(searchSupportFunds[0], 0);
					searchSupportFundHigh = NumberParser.parseToInt(searchSupportFunds[1], 0) - 1;
				}
				else
				{
					searchSupportFundLow = NumberParser.parseToInt(searchSupportFunds[0], 0);
					searchSupportFundHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchTotalFee))
			{
				String[] searchTotalFees = searchTotalFee.split("~");
				
				if (searchTotalFees.length == 2)
				{
					searchTotalFeeLow = NumberParser.parseToInt(searchTotalFees[0], 0);
					searchTotalFeeHigh = NumberParser.parseToInt(searchTotalFees[1], 0) - 1;
				}
				else
				{
					searchTotalFeeLow = NumberParser.parseToInt(searchTotalFees[0], 0);
					searchTotalFeeHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchMonthlyRentalFee))
			{
				String[] searchMonthlyRentalFees = searchMonthlyRentalFee.split("~");
				
				if (searchMonthlyRentalFees.length == 2)
				{
					searchMonthlyRentalFeeLow = NumberParser.parseToInt(searchMonthlyRentalFees[0], 0);
					searchMonthlyRentalFeeHigh = NumberParser.parseToInt(searchMonthlyRentalFees[1], 0) - 1;
				}
				else
				{
					searchMonthlyRentalFeeLow = NumberParser.parseToInt(searchMonthlyRentalFees[0], 0);
					searchMonthlyRentalFeeHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchCommision))
			{
				String[] searchCommisions = searchCommision.split("~");
				
				if (searchCommisions.length == 2)
				{
					searchCommisionLow = NumberParser.parseToInt(searchCommisions[0], 0);
					searchCommisionHigh = NumberParser.parseToInt(searchCommisions[1], 0) - 1;
				}
				else
				{
					searchCommisionLow = NumberParser.parseToInt(searchCommisions[0], 0);
					searchCommisionHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchServiceCharge))
			{
				String[] searchServiceCharges = searchServiceCharge.split("~");
				
				if (searchServiceCharges.length == 2)
				{
					searchServiceChargeLow = NumberParser.parseToFloat(searchServiceCharges[0], 0f);
					searchServiceChargeHigh = NumberParser.parseToFloat(searchServiceCharges[1], 0f) - 1f;
				}
				else
				{
					searchServiceChargeLow = NumberParser.parseToFloat(searchServiceCharges[0], 0f);
					searchServiceChargeHigh = Float.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchSalesPerDay))
			{
				String[] searchSalesPerDays = searchSalesPerDay.split("~");
				
				if (searchSalesPerDays.length == 2)
				{
					searchSalesPerDayLow = NumberParser.parseToInt(searchSalesPerDays[0], 0);
					searchSalesPerDayHigh = NumberParser.parseToInt(searchSalesPerDays[1], 0) - 1;
				}
				else
				{
					searchSalesPerDayLow = NumberParser.parseToInt(searchSalesPerDays[0], 0);
					searchSalesPerDayHigh = Integer.MAX_VALUE;
				}
			}
			
			if (StringUtils.isNotEmpty(searchSalesPerMonth))
			{
				String[] searchSalesPerMonths = searchSalesPerMonth.split("~");
				
				if (searchSalesPerMonths.length == 2)
				{
					searchSalesPerMonthLow = NumberParser.parseToInt(searchSalesPerMonths[0], 0);
					searchSalesPerMonthHigh = NumberParser.parseToInt(searchSalesPerMonths[1], 0) - 1;
				}
				else
				{
					searchSalesPerMonthLow = NumberParser.parseToInt(searchSalesPerMonths[0], 0);
					searchSalesPerMonthHigh = Integer.MAX_VALUE;
				}
			}
			
			List<Pair<String, OrderBy>> sortConditions = SortQuery.getSortConditions(request, toServer.getiSortingCols());
			
			List<Foundation> foundations = new ArrayList<Foundation>();
			
			Integer filteredCount = this._foundationService.listFoundations(searchCondition,
					searchLeaseDepositLow, searchLeaseDepositHigh,
					searchFacilitiesInvestmentLow, searchFacilitiesInvestmentHigh,
					searchPremiumLow, searchPremiumHigh,
					searchUnionFeeLow, searchUnionFeeHigh,
					searchSupportFundLow, searchSupportFundHigh,
					searchTotalFeeLow, searchTotalFeeHigh,
					searchMonthlyRentalFeeLow, searchMonthlyRentalFeeHigh,
					searchCommisionLow, searchCommisionHigh,
					searchServiceChargeLow, searchServiceChargeHigh,
					searchSalesPerDayLow, searchSalesPerDayHigh,
					searchSalesPerMonthLow, searchSalesPerMonthHigh,
					toServer.getPage(),
					toServer.getiDisplayLength(),
					sortConditions,
					foundations);
			
			map.setiTotalRecords(this._foundationService.countFoundation());
			map.setiTotalDisplayRecords(filteredCount);
			
			map.put("foundations", foundations);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 매장 열람 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param foundationId 열람하려는 매장의 아이디가 전달된다.
	 * @return 매장 열람 결과를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RolesAllowed("ROLE_ADMIN")
	@RequestMapping(value = "/get", method = { RequestMethod.GET, RequestMethod.POST })
	public ModelAndView getFoundation(HttpServletRequest request, Long foundationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			Foundation foundation = this._foundationService.getFoundation(foundationId);
			
			map.put("foundation", foundation);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 매장 저장 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param foundation 저장하려는 매장 정보가 전달된다.
	 * @return 매장 저장 결과를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RolesAllowed("ROLE_ADMIN")
	@RequestMapping(value = "/save", method = { RequestMethod.GET, RequestMethod.POST })
	public ModelAndView saveFoundation(HttpServletRequest request,
			@RequestParam(value = "foundationId", required = false, defaultValue = "0")Long foundationId,
			Foundation foundation)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			boolean result = this._foundationService.saveFoundation(foundationId, foundation);
			
			map.put("result", result);
			map.put("foundation", foundation);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
}